import type { AxiosError, AxiosInstance, AxiosRequestConfig } from "axios";
import type {
  AxiosHooks,
  HttpResponse,
  HttpError,
  HttpRequestConfig,
} from "./type";
import axios from "axios";
import { Base64 } from "js-base64";
import { checkStatus } from "./checkStatus";
import { WHITELIST } from "./constants";
import { getToken, formatToken } from "@/utils/auth";
import NProgress from "../npprogress";

export const axiosHooks: AxiosHooks = {
  /**
   * @description 请求前处理请求参数
   */
  beforeRequestHook: (
    config: AxiosRequestConfig,
    options: HttpRequestConfig
  ) => {
    return config;
  },

  beforeResponseHook: (res: HttpResponse, options: HttpRequestConfig) => {
    const { isRawRes } = options;
    if (!res) return; // 被取消的请求
    // 不进行任何处理，直接返回
    // NOTE: 用于页面代码可能需要直接获取code，data，message这些信息时开启，也适用于返回 blob 流数据
    if (isRawRes) {
      return res;
    }

    let data;
    res?.config?.responseType == "blob" || !res.config // res.config在token过期的时候这个方法会走两次第二次不是完整的请求体没有config，所以只能返回res
      ? (data = res)
      : (data = res.data); // 响应数据是blob类型的时候返回整个响应体，方便取响应头里面的数据
    if (!data) {
      throw new Error("http 请求无返回值");
    }
    return data;
  },

  /**
   * @description: 请求拦截器处理
   */
  requestInterceptors: (config, options) => {
    // 开启进度条动画
    NProgress.start();
    // Cup Authorization header
    config.headers["Authorization"] = `Basic ${Base64.encode(
      `${"saber"}:${"saber_secret"}`
    )}`;
    // Cup Token header
    if (!WHITELIST.some((url) => config.url.includes(url))) {
      config.headers["Cup-Auth"] = formatToken(getToken().access_token);
    }

    // Cup 根据配置文件替换请求接口地址 baseurl
    if (import.meta.env.MODE !== "development" && window.SYS_CONFIG) {
      const sysConfig = window.SYS_CONFIG.ProxyApi;
      for (const key in sysConfig) {
        if (config.url?.indexOf("/" + key) === 0) {
          config.url = config.url.replace("/" + key, sysConfig[key]);
        } else if (config?.url?.indexOf(key) === 0) {
          config.url = config.url.replace(key, sysConfig[key]);
        }
      }
    }
    return config;
  },

  /**
   * @description: 请求错误处理
   */
  // requestInterceptorsCatch: (error: HttpError) => {
  //   return Promise.reject(error);
  // },

  /**
   * @description: 响应拦截器处理
   */
  responseInterceptors: (res: HttpResponse) => {
    // 关闭进度条动画
    NProgress.done();
    return res;
  },

  /**
   * @description: 响应错误处理
   */
  responseInterceptorsCatch: (
    axiosInstance: AxiosInstance,
    error: HttpError
  ) => {
    // 所有的响应异常 区分来源为取消请求/非取消请求
    error.isCancelRequest = axios.isCancel(error);
    if (error.isCancelRequest) return; // 如果是重复、取消后的请求，不返回错误给用户
    return checkStatus(error);
  },
};
